package com.scaffold.myproject.config;

import com.scaffold.myproject.common.Result;
import com.scaffold.myproject.common.BizException;
import com.scaffold.myproject.common.CodeMsg;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * 全局异常
 **/
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 缺失参数异常处理器
     *
     * @param e 缺失参数异常
     * @return ResponseResult
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Result parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
        return Result.error(CodeMsg.SERVER_ERROR.getCode(), "请求参数 " + e.getParameterName() + " 不能为空");
    }


    /**
     * 缺少请求体异常处理器
     *
     * @param e 缺少请求体异常
     * @return ResponseResult
     */

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
        return Result.error(CodeMsg.SERVER_ERROR.getCode(), "参数体不能为空");
    }


    /**
     * 自定义异常
     **/
    @ExceptionHandler(value = BizException.class)
    public Result handle(BizException e) {
        return Result.error(e.getCode(), e.getMsg());
    }

    /**
     * 全局异常
     **/
    @ExceptionHandler(Exception.class)
    public Result exceptionHandler(HttpServletRequest request, Exception exception) throws Exception {
        String message = exception.getMessage() + request.getRequestURL().toString();
        return Result.error(CodeMsg.SERVER_ERROR.getCode(), message);
    }

    /**
     * 校验异常
     **/
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Result handleValidException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        StringBuilder message = new StringBuilder();
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message.append(fieldError.getDefaultMessage()).append("!");
            }
        }
        return Result.error(CodeMsg.BIND_ERROR.getCode(), message.toString());
    }


    /**
     * 如果是controller方法中单个参数的校验, 则需要捕获该异常
     * 如方法参数：@Length(max = 4) @RequestParam("username") String username
     * 需要在controller类上添加@Validated，否则不生效
     **/
    @ExceptionHandler(value = ConstraintViolationException.class)
    public Result handleConstraintViolationException(ConstraintViolationException e) {
        StringBuilder message = new StringBuilder();
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        constraintViolations.stream().forEach(item -> {
            message.append(item.getMessage()).append("!");
        });
        return Result.error(CodeMsg.BIND_ERROR.getCode(), message.toString());
    }
}